﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using Conducido.WcfMessageLogger.Services.Behaviors.Entities;
using Conducido.WcfMessageLogger.Services.Behaviors.Entities.Config;
using Conducido.WcfMessageLogger.Services.Behaviors.Logger;

namespace Conducido.WcfMessageLogger.Services.Behaviors
{
    /// <summary>
    /// Message inspector
    /// </summary>
    public class ServiceMessagelogInspector : IDispatchMessageInspector
    {
        private MessageLogConfiguration _messageLogConfiguration;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="wayOfLogging"></param>
        /// <param name="serviceMessageLogTransport"></param>
        /// <param name="uri"></param>
        public ServiceMessagelogInspector(MessageLogType wayOfLogging, ServiceMessageLogType serviceMessageLogTransport, string uri)
        {
            _messageLogConfiguration = new MessageLogConfiguration(wayOfLogging, serviceMessageLogTransport, uri);
        }

        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            DateTime timestamp = DateTime.Now.ToUniversalTime();    //Caught as early as possible a timestamp
                                                                    
            // Empty messages will also pass the messageinspectors. 
            // eg. *.svc?wsdl will also triggers the behavior and inspectors
            if (request == null || request.IsEmpty)
            {
                return null;
            }

            var logOperator = new LogOperator(request, _messageLogConfiguration);
            logOperator.LogIncoming(timestamp, false);
            request = logOperator.CopyMessage();

            return logOperator.CreateCorrelatedInformation();
        }

        public void BeforeSendReply(ref Message reply, object correlationState)
        {
            DateTime timestamp = DateTime.Now.ToUniversalTime();

            if (reply == null || reply.IsEmpty ||
                    (reply.Headers.MessageVersion.Addressing == AddressingVersion.None
                    && reply.Headers.MessageVersion.Envelope == EnvelopeVersion.None)) //No need to log wsdl messages
            {
                return;
            }

            
            if (correlationState.GetType() == typeof(CorrelatedInformation))
            {
                var logOperator = new LogOperator(reply, (CorrelatedInformation) correlationState, _messageLogConfiguration);
                logOperator.LogOutgoing(timestamp, false);
                reply = logOperator.CopyMessage();
            }
        }
    }
}
